package com.itmumu.miniwechat.common.handler;

import com.itmumu.miniwechat.common.domain.response.ApiResult;
import com.itmumu.miniwechat.common.exception.BusinessException;
import com.itmumu.miniwechat.common.exception.CommonErrorEnum;
import com.itmumu.miniwechat.common.exception.JwtVerifyException;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Path;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * validation参数校验异常
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ApiResult methodArgumentNotValidExceptionExceptionHandler(MethodArgumentNotValidException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(), message.substring(0, message.length() - 1));
    }

    // 捕获 @RequestParam 或 @PathVariable 校验失败异常
    @ExceptionHandler(ConstraintViolationException.class)
    public ApiResult handleConstraintViolationException(ConstraintViolationException e) {
        StringBuilder errorMsg = new StringBuilder();

        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            String message = violation.getMessage();
            errorMsg.append(message).append(",");
        }

        log.info("validation parameters error！The reason is:{}", errorMsg.toString());
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(), errorMsg.substring(0, errorMsg.length() - 1));
    }


    /**
     * validation参数校验异常
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(value = BindException.class)
    public ApiResult bindException(BindException e) {
        StringBuilder errorMsg = new StringBuilder();
        e.getBindingResult().getFieldErrors().forEach(x -> errorMsg.append(x.getField()).append(x.getDefaultMessage()).append(","));
        String message = errorMsg.toString();
        log.info("validation parameters error！The reason is:{}", message);
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(), message.substring(0, message.length() - 1));
    }

    /**
     * 处理空指针的异常
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = NullPointerException.class)
    public ApiResult exceptionHandler(NullPointerException e) {
        log.error("null point exception！The reason is: ", e);
        return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
    }

    /**
     * 身份校验失败
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(JwtVerifyException.class)
    public ApiResult exception(JwtVerifyException e) {
        // 控制台打印异常  借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));

        // 返回错误信息
        return ApiResult.fail(CommonErrorEnum.UNAUTHORIZED.getCode(), CommonErrorEnum.UNAUTHORIZED.getMessage());
    }

    /**
     * 未知异常
     */
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public ApiResult systemExceptionHandler(Exception e) {
        log.error("system exception！The reason is：{}", e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.SYSTEM_ERROR);
    }

    /**
     * 自定义校验异常（如参数校验等）
     */
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = BusinessException.class)
    public ApiResult businessExceptionHandler(BusinessException e) {
        log.info("business exception！The reason is：{}", e.getMessage(), e);
        return ApiResult.fail(CommonErrorEnum.PARAM_VALID.getCode(), e.getMessage());
    }

    /**
     * http请求方式不支持
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ApiResult<Void> handleException(HttpRequestMethodNotSupportedException e) {
        log.error(e.getMessage(), e);
        return ApiResult.fail(-1, String.format("不支持'%s'请求", e.getMethod()));
    }

    /**
     * 限流异常
     */
//    @ResponseStatus(HttpStatus.TOO_MANY_REQUESTS)
//    @ExceptionHandler(value = FrequencyControlException.class)
//    public ApiResult frequencyControlExceptionHandler(FrequencyControlException e) {
//        log.info("frequencyControl exception！The reason is：{}", e.getMessage(), e);
//        return ApiResult.fail(e.getErrorCode(), e.getMessage());
//    }
}
